package com.terrace.db.quartz.service.impl;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.terrace.db.constant.DBType;
import com.terrace.db.quartz.dao.QuartzDao;
import com.terrace.db.quartz.mapper.entity.SchedulerJob;
import com.terrace.db.quartz.service.QuartzService;
import com.terrace.core.mybatis.entity.Pagination;
import com.terrace.core.mybatis.plugin.pagination.PaginationHelper;
import com.terrace.core.utils.ApplicationContextUtil;
import com.terrace.core.spring.datasource.annotation.DataSource;

@Service
@Transactional
@SuppressWarnings("unchecked")
@DataSource(name = DBType.ADMIN)
public class QuartzServiceImpl implements QuartzService {
	
	@Autowired
	private QuartzDao quartzDao;

	@Override
	public void addSchedulerJob(SchedulerJob job) throws Exception {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
		// 触发器不存在，创建一个
		if (!scheduler.checkExists(triggerKey)) {
			Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(job.getJobClazz());
			JobBuilder jobBuilder = JobBuilder.newJob(jobClass);
			jobBuilder.withIdentity(job.getJobName(), job.getJobGroup());
			jobBuilder.withDescription(job.getJobDescription());
			JobDetail jobDetail = jobBuilder.build();
			
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
			TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
			triggerBuilder.withIdentity(job.getJobName(), job.getJobGroup());
			triggerBuilder.withDescription(job.getJobDescription());
			CronTrigger trigger = triggerBuilder.withSchedule(scheduleBuilder).build();
			scheduler.scheduleJob(jobDetail, trigger);
		}
	}

	@Override
	public void deleteSchedulerJob(SchedulerJob job)  throws Exception {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.deleteJob(jobKey);
	}

	@Override
	public void updateSchedulerJob(SchedulerJob job) throws Exception {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
		TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
		triggerBuilder.withIdentity(job.getJobName(), job.getJobGroup());
		triggerBuilder.withDescription(job.getJobDescription());
		trigger = triggerBuilder.withSchedule(scheduleBuilder).build();
		scheduler.rescheduleJob(triggerKey, trigger);
	}

	@Override
	public void pauseSchedulerJob(SchedulerJob job) throws Exception {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.pauseJob(jobKey);
	}

	@Override
	public void immediatelyExecuteSchedulerJob(SchedulerJob job) throws Exception {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.triggerJob(jobKey);
	}
	
	@Override
	public void resumeSchedulerJob(SchedulerJob job) throws Exception {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.resumeJob(jobKey);
	}
	
	@Override
	public boolean checkSchedulerExists(SchedulerJob job) throws SchedulerException {
		SchedulerFactoryBean schedulerFactoryBean = ApplicationContextUtil.getContext().getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
		return scheduler.checkExists(triggerKey);
	}
	
	@Override
	public SchedulerJob selectSchedulerJobByPrimaryKey(String schedName, String jobName, String jobGroup) {
		return quartzDao.selectSchedulerJobByPrimaryKey(schedName, jobName, jobGroup);
	}

	@Override
	public Pagination<SchedulerJob> selectSchedulerJobForPagination(Pagination<SchedulerJob> pagination, SchedulerJob job) {
		PaginationHelper.prepare(pagination);
		return PaginationHelper.execute(quartzDao.selectSchedulerJobForPagination(job));
	}

}
